<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<style type="text/css">
		*,body{
			padding: 0;
			margin: 0;
		}
		ul,li{
			list-style: none;
		}
		.drag-sort{
			position: relative;
			width: 200px;
			height: 280px;
			border: 1px solid #eee;
		}
		.drag-sort-wrap{
			position: relative;
		}
		.drag-sort-item{
			position: absolute;
			left: 0;
			width: 200px;
			display: flex;
			justify-content: center;
			align-items: center;
			height: 40px;
			background-color: #fff;
			border-bottom: 1px solid #eee;
			box-sizing: border-box;
		}
		.drag-sort-item.move{
			position: fixed;
			opacity: 0.5;
			border: 1px solid #eee;
			pointer-events: none;
			top: 999;
		}
		.drag-sort-item.hover{
			background-color: #eee;
		}
		.drag-sort-item.draggable{
			background-color: rgb(233,237,245);
		}
		.drag-sort-placeholder{
			position: absolute;
			left: 0;
			top: 0;
			z-index: 9999;
			width: 100%;
			height: 1px;
			background-color: #007AFF;
			pointer-events: none;
		}
		.drag-sort-placeholder.hide{
			display: none;
		}
	</style>
	<body>
		<div class="drag-sort">
			<div class="drag-sort-wrap">
				
			</div>
			<div class="drag-sort-placeholder hide"></div>
			<!-- <div class="drag-sort-item">1</div>
			<div class="drag-sort-item">2</div>
			<div class="drag-sort-item">3</div>
			<div class="drag-sort-item">4</div>
			<div class="drag-sort-item">5</div>
			<div class="drag-sort-item">6</div>
			<div class="drag-sort-item">7</div> -->
		</div>
		<script type="text/javascript">
			let listSort = (function(){
				// 获取dom
				let dragSort = document.querySelector('.drag-sort')
				let dragSortWrap = document.querySelector('.drag-sort-wrap')
				let dragSortPlaceholder = document.querySelector('.drag-sort-placeholder')
				let dragSortPlaceholderIndex = 0;
				let fixedDomInstance = null;
				// 移上去需要高亮的元素
				let hoverLightDom = null;
				let eleHeight = 40;
				let currentIndex = 0;
				// 鼠标点击元素，距离元素顶点的偏移值
				let mouseDownOffsetX = 0;
				let mouseDownOffsetY = 0;
				// 排序值,越小排在前面
				let sortNum = -1099511627776;
				// 列表数据
				let data = []
				// 获取数据
				const getData = ()=>{
					data = [
						{id:0,text:1},
						{id:1,text:2},
						{id:2,text:3},
						{id:3,text:4},
						{id:4,text:5},
						{id:5,text:6},
						{id:6,text:7}
					]
					// 设置排序值
					data = data.map((item,index)=>{
						item.sort = sortNum*(index+1)
						return item
					})
					// 冒泡排序
					data = bubbleSort(data)
					// 设置位置
					data = data.map((item,index)=>{
						item.top = 40*index
						return item
					})
				}
				// 渲染列表
				const renderList = ()=>{
					let str=``;
					data.map((item,index)=>{
						str+=`<div class="drag-sort-item" data-index="${index}" style="top:${item.top}px">${item.text}</div>`
					})
					dragSortWrap.innerHTML = str
					console.log(data);
				}
				// 创建跟随鼠标移动的dom
				const fixedDomMove = ({left,top,mouseDownOffsetX,mouseDownOffsetY}={})=>{
					fixedDomInstance.style.top = top-mouseDownOffsetY+"px"
					fixedDomInstance.style.left = left-mouseDownOffsetX+"px"
				}
				// 销毁dom
				const destoryFixedDom = ()=>{
					if(fixedDomInstance){
						document.querySelector('body').removeChild(fixedDomInstance)
						fixedDomInstance = null;
					}
				}
				// 拖动到元素上高亮
				const dragHoverLight = (target,className='hover')=>{
					// 当移上去需要高亮的元素，移动的时候在同一元素上时，不进行重复操作移除添加class
					if(!hoverLightDom || hoverLightDom!=target){
						hoverLightDom = target;
						dragRemoveHoverLight()
						target.classList.add(className)
					}
					
				}
				// 移除高亮
				const dragRemoveHoverLight = (className='hover')=>{
					let items = dragSortWrap.querySelectorAll('.drag-sort-item')
					Array.from(items).map(item=>{
						item.classList.remove(className)
					})
				}
				// 获取拖动到元素上的区域
				const getDragToEleArea = ({offsetX=0,offsetY=0,index=0})=>{
					console.log(index);
					if( isNaN(index) || currentIndex==index) {
						dragSortPlaceholder.classList.add('hide')
						return false
					}
					if(offsetY > eleHeight/2){
						dragSortPlaceholderIndex = index+1
					}else{
						dragSortPlaceholderIndex = index
					}
					dragSortPlaceholder.classList.remove('hide')
					dragSortPlaceholder.style.top = dragSortPlaceholderIndex * eleHeight +'px'
				}
				const setElementSort = ()=>{
					if(dragSortPlaceholderIndex==0){
						let sort = data[dragSortPlaceholderIndex].sort + sortNum
						data[currentIndex].sort = sort
					}else if(dragSortPlaceholderIndex==currentIndex){
						
					}else if(dragSortPlaceholderIndex>0 && dragSortPlaceholderIndex<data.length){
						let sort = (data[dragSortPlaceholderIndex].sort+data[dragSortPlaceholderIndex-1].sort) / 2
						data[currentIndex].sort = sort
					}else if(dragSortPlaceholderIndex==data.length){
						let sort = data[dragSortPlaceholderIndex-1].sort - sortNum
						data[currentIndex].sort = sort
					}
					
					let _data = JSON.parse(JSON.stringify(data))
					data = bubbleSort(_data)
					data = data.map((item,index)=>{
						item.top = 40*index
						return item
					})
					console.log(data);
				}
				const bubbleSort = (arr) => {
				   const len = arr.length  
				       for(let i=0;i<len;i++) {
				           let flag = false
				           for(let j=0;j<len-1-i;j++) {
				               if(arr[j].sort > arr[j+1].sort) {
				                   [arr[j], arr[j+1]] = [arr[j+1], arr[j]]
				                   // 只要发生了一次交换，就修改标志位
				                   flag = true
				               }
				           }
				           // 若一次交换也没发生，则说明数组有序，直接放过
				           if(flag == false)  return arr;
				       }
				       return arr
				}
				// const resetVar
				const downFn = (e)=>{
					e.preventDefault();
					mouseDownOffsetX = e.offsetX;
					mouseDownOffsetY = e.offsetY;
					currentIndex = e.target.dataset.index
					e.target.classList.add('draggable')
					fixedDomInstance = e.target.cloneNode(true)
					fixedDomInstance.classList.add('move')
					document.querySelector('body').appendChild(fixedDomInstance)
					window.addEventListener('mousemove',downMove)
					window.addEventListener('mouseup',downUp)
				}
				const downMove = (e)=>{
					e.preventDefault();
					let top = e.pageY;
					let left = e.pageX
					dragHoverLight(e.target)
					fixedDomMove({top,left,mouseDownOffsetX,mouseDownOffsetY})
					getDragToEleArea({offsetX:e.offsetX,offsetY:e.offsetY,index:parseInt(e.target.dataset.index)})
				}
				const downUp = (e)=>{
					// 在拖动元素上释放，才进行排序，重新渲染页面
					if(e.target.classList.contains('drag-sort-item')){
						console.log('sort');
						setElementSort()
						renderList()
					}
					// 隐藏占位线
					dragSortPlaceholder.classList.add('hide')
					// 销毁浮动dom
					destoryFixedDom()
					// 移除拖动元素高亮
					dragRemoveHoverLight()
					dragRemoveHoverLight('draggable')
					window.removeEventListener('mousemove',downMove)
					window.removeEventListener('mousedown',downUp)
				}
				return {
					init:function(){
						getData()
						renderList()
						dragSort.addEventListener('mousedown',downFn)
					}
				}
				
			})()
			listSort.init()
		</script>
	</body>
</html>
